package com.boot.security.service.authorization;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.log.LogMessage;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.annotation.Nullable;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @author 霜寒 <1621856595@qq.com>
 * @description 此过滤器检查请求是否符合权限
 * @date 2020/2/18 17:56
 **/
@Slf4j
public class AuthorizationFilter extends FilterSecurityInterceptor {

    private @Nullable RequestMatcher ignore;


    public AuthorizationFilter(FilterInvocationSecurityMetadataSource securityMetadataSource,
                               TokenAuthorizationManager manager) {
        securityMetadataSource.getAllConfigAttributes();
        setSecurityMetadataSource(securityMetadataSource);
        setAccessDecisionManager(manager);
    }

    public AuthorizationFilter(RequestMatcher ignore,
                               FilterInvocationSecurityMetadataSource securityMetadataSource,
                               TokenAuthorizationManager manager) {
        this.ignore = ignore;
        securityMetadataSource.getAllConfigAttributes();
        setSecurityMetadataSource(securityMetadataSource);
        setAccessDecisionManager(manager);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (ignoreRequest((HttpServletRequest) request)) {
            chain.doFilter(request, response);
        } else {
            log.info("==================================== AuthorizationFilter ===================================");
            invoke(new FilterInvocation(request, response, chain));
        }

    }

    protected boolean ignoreRequest(HttpServletRequest request) {
        if (ignore != null && ignore.matches(request)) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace(LogMessage.format("request match to %s , ignore", ignore));
            }
            return true;
        }
        return false;
    }
}
